from django.db.models import F
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from django.urls import reverse
from django.views import generic

from polls.models import Question, Choice


# Create your views here.
class IndexView(generic.ListView):
    template_name = "polls/index.html"
    context_object_name = "latest_question_list"
    # context = {"latest_question_list": latest_question_list}
    # 对于 ListView， 自动生成的 context 变量是 question_list,提供 context_object_name 属性，表示我们想使用 latest_question_list。
    def get_queryset(self):
        # 默认情况下，它返回 queryset 属性值
        """Return the last five published questions."""
        # 返回一个包含 Question 的 pub_date 小于或等于（即，早于或等于） timezone.now 的时间查询集。
        return Question.objects.filter(pub_date__lte=timezone.now()).order_by("-pub_date")[:5]
class DetailView(generic.DetailView):
    #  Django 能够为 context 变量决定一个合适的名字 之前的context = {"question": question}
    #   model = Question 只是 queryset = Question.objects.get(pk=question_id)  的简写
    # DetailView 依赖于 SingleObjectMixin ，它提供一个 get_object() 方法，
    # 该方法根据请求的 URL 来找出对象（它查找 URLconf 中声明的 pk 和 slug 关键字参数，并从视图上的 model 属性查找对象，或者从提供的 queryset 属性中查找
    model = Question
    # 默认模板：polls/question_detail.html （ <app name>/<model name>_detail.html ）
    template_name = "polls/detail.html"

    def get_queryset(self):
        """
        Excludes any questions that aren't published yet.
        """
        return Question.objects.filter(pub_date__lte=timezone.now())


class ResultsView(generic.DetailView):
    model = Question
    template_name = "polls/results.html"


def vote(request, question_id):
    #  根据提供的question_id获取问题对象，如果不存在则返回404错误
    question = get_object_or_404(Question, pk=question_id)
    try:
        # 尝试从POST数据中获取用户选择的选项
        # request.POST 是一个类字典对象，让你可以通过关键字的名字获取提交的数据。
        # 这个例子中， request.POST['choice'] 以字符串形式返回选择的 Choice 的 ID。
        # request.POST 的值永远是字符串。
        selected_choice = question.choice_set.get(pk=request.POST["choice"])
    except (KeyError, Choice.DoesNotExist):
        # 如果用户未选择选项或选项不存在，重新显示投票表单并提示错误消息
        return render(
            request,
            "polls/detail.html",
            {
                "question": question,
                "error_message": "You didn't select a choice.",
            },
        )
    else:
        # 如果用户选择了选项，增加选项的投票计数并保存
        # F("votes") + 1 指示数据库将投票数增加1。
        selected_choice.votes = F("votes") + 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        # 用户将要被重定向的 URL
        # reverse() 调用将返回一个这样的字符串 "/polls/3/results/"
        return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))